/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package knn;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 *
 * @author Nguyen Thuy Ngoc <ntngoc1988@gmail.com>
 */
public class knnHelper<T extends ISample> {

    Map<String, List<T>> sampleByClass;
    List<T> trainingSet;
    List<T> testingSet;

    private void reset() {
        if (sampleByClass != null) {
            sampleByClass.clear();
        }

        if (trainingSet != null) {
            trainingSet.clear();
        }

        if (testingSet != null) {
            testingSet.clear();
        }
    }

    public void splitTrainingAndTestingSets(List<T> samples, double ratio) {
        reset();
        categorizeSamples(samples);
        splitTrainingAndTestingSets(ratio);
    }

    private void categorizeSamples(List<T> samples) {
        sampleByClass = new HashMap<String, List<T>>();

        for (T iSample : samples) {
            if (sampleByClass.containsKey(iSample.getAssignedClass())) {
                List<T> classSamples = sampleByClass.get(iSample.getAssignedClass());
                classSamples.add(iSample);

            } else {
                List<T> classSamples = new ArrayList<T>();
                classSamples.add(iSample);
                sampleByClass.put(iSample.getAssignedClass(), classSamples);
            }
        }
    }

    private void splitTrainingAndTestingSets(double ratio) {
        trainingSet = new ArrayList<T>();
        testingSet = new ArrayList<T>();
        for (String classKey : sampleByClass.keySet()) {
            List<T> classSamples = sampleByClass.get(classKey);

            int size = classSamples.size();
            int trainingSize = (int) Math.floor(size * ratio);

            Random rand = new Random(new Date().getTime());
            for (int i = 0; i < trainingSize; i++) {
                int trainingSampleIdx = Math.abs(rand.nextInt()) % classSamples.size();

                trainingSet.add(classSamples.get(trainingSampleIdx));
                classSamples.remove(trainingSampleIdx);
            }

            testingSet.addAll(classSamples);
        }
    }

    public List<T> getTrainingSet() {
        return trainingSet;
    }

    public List<T> getTestingSet() {
        return testingSet;
    }
}